package ioc;

import org.dom4j.DocumentException;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * IOC容器实现类
 */
public class ClassPathXmlApplicationContext {
    // 存储Bean定义
    private List<BeanDefinition> beanDefinitions;

    // 存储实例化的Bean
    private Map<String, Object> singletonBeans = new HashMap<>();

    public ClassPathXmlApplicationContext(String xmlPath) throws DocumentException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        // 解析XML配置文件，获取Bean定义
        XmlParser xmlParser = new XmlParser();
        beanDefinitions = xmlParser.parseXml(xmlPath);

        // 初始化所有的Bean
        initializeBeans();
    }

    /**
     * 初始化所有的Bean
     */
    private void initializeBeans() throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
        for (BeanDefinition beanDefinition : beanDefinitions) {
            if (!singletonBeans.containsKey(beanDefinition.getId())) {
                createBean(beanDefinition);
            }
        }
    }

    /**
     * 创建Bean实例
     */
    private Object createBean(BeanDefinition beanDefinition) throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
        // 获取类名并加载类
        String className = beanDefinition.getClassName();
        Class<?> clazz = Class.forName(className);

        // 使用默认构造函数创建实例
        Constructor<?> constructor = clazz.getDeclaredConstructor();
        Object instance = constructor.newInstance();

        // 设置属性
        setProperties(instance, beanDefinition);

        // 将实例存入容器
        singletonBeans.put(beanDefinition.getId(), instance);

        return instance;
    }

    /**
     * 为Bean设置属性
     */
    private void setProperties(Object instance, BeanDefinition beanDefinition) throws IllegalAccessException {
        Class<?> clazz = instance.getClass();
        Map<String, String> properties = beanDefinition.getProperties();

        for (Map.Entry<String, String> entry : properties.entrySet()) {
            String propertyName = entry.getKey();
            String propertyValue = entry.getValue();

            try {
                // 获取属性对应的Field对象
                Field field = clazz.getDeclaredField(propertyName);
                field.setAccessible(true); // 设置私有字段可访问

                // 根据字段类型设置值
                Class<?> fieldType = field.getType();
                if (fieldType == String.class) {
                    field.set(instance, propertyValue);
                } else if (fieldType == int.class || fieldType == Integer.class) {
                    field.set(instance, Integer.parseInt(propertyValue));
                } else if (fieldType == double.class || fieldType == Double.class) {
                    field.set(instance, Double.parseDouble(propertyValue));
                }
                // 可以根据需要扩展更多类型
            } catch (NoSuchFieldException e) {
                throw new RuntimeException("Bean " + beanDefinition.getId() + " 没有属性 " + propertyName, e);
            }
        }
    }

    /**
     * 根据id获取Bean
     */
    public Object getBean(String id) {
        return singletonBeans.get(id);
    }

    /**
     * 根据类型获取Bean
     */
    @SuppressWarnings("unchecked")
    public <T> T getBean(Class<T> type) {
        for (Object bean : singletonBeans.values()) {
            if (type.isInstance(bean)) {
                return (T) bean;
            }
        }
        return null;
    }
}
